#ifndef NET_MSG_H_
#define NET_MSG_H_

#define MESSAGE_SIZE 512
enum IO { _INPUT, _OUTPUT };
enum eGamePhase{WAITING,INPROGRESS,FINISH,SHUTDOWN,DISCONNECTED};
enum eMessage{C_CON,SV_ACC,SV_FULL,C_ALIVE,C_INPUT,SV_SNAPSHOT,SV_C_CLOSE};
#define DISCONNECT -3
#define SUCCESS 0

#include <WinSock2.h>
#pragma comment(lib, "Ws2_32.lib")

class NetworkMsg
{
    private:
        char dataBuffer[MESSAGE_SIZE];
		int begin, end;
		IO type;

    public:
        NetworkMsg(IO _type);
		int getBufferSize();
		char* getReadBuffer();
		const char* getSendBuffer();
		int getLength();
		void setEnd(int _end);
 		int read(char* data, int offset, int length);
		int readString(char* data, int length);

		// Will read a data type from the message and return it.
		char readByte();
        short readShort();
		int readInt();
		float readFloat();

		void write(const char* data, int offset, int length);

		void writeString(const char *data);
		void writeString(const char *data, int length);

		// Will write a data type to the message buffer without sending it.
		void writeByte(char output);
        void writeShort(short output);
        void writeInt(int output);
        void writeFloat(float output);

		void reset(IO _type);

		void reset();

		int bytesAvailable();


	private:
		// Simplified functions for reading / writing raw data to the buffer.
		int rawRead(char* data, int length, bool partialOkay);
		void rawWrite(const char* data, int length);

		// Robust functions for reading / writing raw data to the buffer.
		int rawRead(char* data, int length, int delimiter, bool partialOkay);
		void rawWrite(const char* data, int length, int delimiter);
};

inline int NetworkMsg::rawRead(char* data, int length, bool partialOkay)
{
	return rawRead(data, length, -1, partialOkay);
}

inline void NetworkMsg::rawWrite(const char* data, int length)
{
	rawWrite(data, length, -1);
}

int recvNetMessage(SOCKET s, NetworkMsg& messages);
int recvfromNetMessage(SOCKET s, NetworkMsg& message, sockaddr_in* source);

int sendNetMessage(SOCKET s, NetworkMsg& message);
int sendtoNetMessage(SOCKET s, NetworkMsg& message, const sockaddr_in* source);
#endif